# -*- coding: utf-8 -*-
"""
Created on Sat Jan  5 22:33:16 2019

@author: william
"""
import tensorflow as tf
import numpy as np
def ft(embeddings, W):
    """
    :param embeddings: the word embeddings of each word in the target
    :param W: the weight of the value of each dimension in embeddings
    """
    answer = np.tanh(W * embeddings)
    return answer

def normalization(ft_values):
    new_representation = np.zeros(ft_values[0].shape)
    fts = np.exp(ft_values)
    summary = np.sum(fts)
    alpha = fts/summary
    for index in range(ft_values.shape[0]):
        new_representation = new_representation + alpha[index] * ft_values[index]
    return new_representation

def fuseInformation(hidden_state, target_representation, W):
    """
    :param hidden_state: the hidden state vector of sentence
    :param target_representation: the representation computed by normalization function
    :param W: the weight matrix with dimension of (2 * d_h + d_w) * d_w
    :return r_i: the target-specific representation of the i-th word in the sentence
    """
    compute_W = W[: hidden_state.shape[0] + target_representation.shape[0]]
    r = np.matmul(compute_W.T, np.concatenate((hidden_state, target_representation), axis = 0))
    return r

def source2AspectAtt(embeddings, W):
    """
    :param embeddings: the embeddings of each words in sentence
    :param W: the weight matrix of each word
    :return normal: the result of source2AspectAttention Layer
    """
    compute_W = W[:embeddings.shape[0]]
    score = ft(embeddings, compute_W)
    normal = normalization(score)
    return normal

def source2ContextAtt(hidden_state, r, W):
    """
    :param hidden_state: the hidden state output of sentence
    :param r: the target-specific representation computed by fuseInformation function
    :param W: the weight matrix with dimension 2 * d_h + d_w
    """
    computed_W = W[:hidden_state.shape[0] + r.shape[0]]
    multiply_result = np.matmul(computed_W.T, np.concatenate((r, hidden_state), axis = 0))
    f_s = np.tanh(multiply_result)
    f_s_exp = np.exp(f_s)
    summary = np.sum(f_s_exp)
    alpha = f_s_exp/summary
    final_r = alpha * hidden_state
    return final_r